<?php


namespace NanQi\Hope\Di;


use NanQi\Hope\Hope;
use Psr\Log\LogLevel;

class StdoutLogger extends \Hyperf\Framework\Logger\StdoutLogger
{
    /**
     * @var bool
     */
    private $colors = true;


    /**
     * @var array
     */
    private static $ansiCodes = [
        'bold'       => 1,
        'fg-black'   => 30,
        'fg-red'     => 31,
        'fg-green'   => 32,
        'fg-yellow'  => 33,
        'fg-blue'    => 34,
        'fg-magenta' => 35,
        'fg-cyan'    => 36,
        'fg-white'   => 37,
        'bg-black'   => 40,
        'bg-red'     => 41,
        'bg-green'   => 42,
        'bg-yellow'  => 43,
        'bg-blue'    => 44,
        'bg-magenta' => 45,
        'bg-cyan'    => 46,
        'bg-white'   => 47,
    ];

    protected function getMessage(string $message, string $level = LogLevel::INFO, array $tags)
    {
        $implodedTags = '';

        foreach ($tags as $value) {
            $implodedTags .= (' [' . $value . ']');
        }
        $date = date('Y-m-d H:i:s');

        switch ($level) {
            case LogLevel::ERROR:
                $color = 'fg-red';
                break;
            case LogLevel::INFO:
                $color = 'fg-green';
                break;
            default:
                $color = 'fg-yellow';
        }

        $level = $this->formatWithColor($color, strtoupper($level));
        return  "{$date} [$level] $message";
    }

    /**
     * Formats a buffer with a specified ANSI color sequence if colors are
     * enabled.
     * @param string $color
     * @param string $buffer
     * @return string
     */
    protected function formatWithColor(string $color, string $buffer): string
    {
        if (Hope::isProduct()) {
            return $buffer;
        }

        if (!$this->colors) {
            return $buffer;
        }

        $codes   = \array_map('\trim', \explode(',', $color));
        $lines   = \explode("\n", $buffer);
        $padding = \max(\array_map('\strlen', $lines));
        $styles  = [];

        foreach ($codes as $code) {
            $styles[] = self::$ansiCodes[$code];
        }

        $style = \sprintf("\x1b[%sm", \implode(';', $styles));

        $styledLines = [];

        foreach ($lines as $line) {
            $styledLines[] = $style . \str_pad($line, $padding) . "\x1b[0m";
        }

        return \implode("\n", $styledLines);
    }
}